using Admin2025.Application.Common;
using Admin2025.Application.Dtos;
using Admin2025.Application.Extensions;
using Admin2025.Domain.Entities.App;
using Admin2025.Domain.Repositories;
using MediatR;

namespace Admin2025.Application.Services;

public class AppUserService : IAppUserService
{
    private readonly IRespository<AppUser> _userRepo;
    private readonly IRespository<AppRole> _roleRepo;
    private readonly IMediator _mediator;

    public AppUserService(IRespository<AppUser> userRepo, IRespository<AppRole> roleRepo, IMediator mediator)
    {
        _userRepo = userRepo;
        _roleRepo = roleRepo;
        _mediator = mediator;
    }

    // 暂时没有考试过滤、查找之类的功能,只考虑了分页，作业：请同时考试一下通用的过滤、查找功能，结合分页一起来
    public async Task<IEnumerable<UserDto>> GetAllAsync(PageRequestDto pageRequestDto)
    {
        var users = await _userRepo.GetPagedAsync(pageRequestDto.PageIndex, pageRequestDto.PageSize);
        return users.Select(u => new UserDto { Id = u.Id, Username = u.Username, Nickname = u.Nickname, AvatarUrl = u.AvatarUrl, IsEnabled = u.IsActived });
    }

    public async Task<UserDto> GetByIdAsync(Guid id)
    {
        var u = await _userRepo.GetByIdAsync(id) ?? throw new Exception("用户不存在");
        return new UserDto { Id = u.Id, Username = u.Username, Nickname = u.Nickname, AvatarUrl = u.AvatarUrl, IsEnabled = u.IsActived };
    }

    public async Task CreateAsync(CreateUserDto dto)
    {
        var salt = Guid.NewGuid().ToString("N");
        var pwdHash = HashPassword(dto.Password, salt);
        
        // 使用静态工厂方法创建用户（会自动发布事件）
        var user = AppUser.Create(dto.Username, pwdHash, salt);
        
        // 保存到数据库
        await _userRepo.CreateAsync(user);
        
        // 发布领域事件
        await _mediator.PublishDomainEventsAsync(user);
    }

    public async Task UpdateAsync(Guid id, UpdateUserDto dto)
    {
        var user = await _userRepo.GetByIdAsync(id) ?? throw new Exception("用户不存在");
        if (!string.IsNullOrEmpty(dto.Nickname)) user.UpdateNickname(dto.Nickname);
        if (!string.IsNullOrEmpty(dto.AvatarUrl)) user.UpdateAvatar(dto.AvatarUrl);
        await _userRepo.UpdateAsync(user);
    }

    public async Task DeleteAsync(Guid id)
    {
        var user = await _userRepo.GetByIdAsync(id) ?? throw new Exception("用户不存在");
        
        // 使用领域方法进行软删除（会自动发布事件）
        user.SoftDelete(Guid.NewGuid()); // TODO: 从当前用户上下文获取操作人ID
        
        // 更新到数据库
        await _userRepo.UpdateAsync(user);
        
        // 发布领域事件
        await _mediator.PublishDomainEventsAsync(user);
    }

    public async Task EnableAsync(Guid id)
    {
        var user = await _userRepo.GetByIdAsync(id) ?? throw new Exception("用户不存在");
        user.Enable();
        await _userRepo.UpdateAsync(user);
    }

    public async Task<ApiResult> DisableAsync(Guid id)
    {
        var user = await _userRepo.GetByIdAsync(id);
        if (user == null)
        {
            return ApiResult.Fail(ErrorCodes.NotFound, "用户不存在或已经删除");
        }

        user.Disable();
        await _userRepo.UpdateAsync(user);
        return ApiResult.Success(user);
    }

    public async Task AssignRoleAsync(Guid userId, Guid roleId)
    {
        var user = await _userRepo.GetByIdAsync(userId) ?? throw new Exception("用户不存在");
        var role = await _roleRepo.GetByIdAsync(roleId) ?? throw new Exception("角色不存在");
        user.AssignRole(role);
        await _userRepo.UpdateAsync(user);
    }

    public async Task RemoveRoleAsync(Guid userId, Guid roleId)
    {
        var user = await _userRepo.GetByIdAsync(userId) ?? throw new Exception("用户不存在");
        var role = await _roleRepo.GetByIdAsync(roleId) ?? throw new Exception("角色不存在");
        user.RemoveRole(role);
        await _userRepo.UpdateAsync(user);
    }

    public async Task UpdateAvatarAsync(Guid userId, string avatarUrl)
    {
        var user = await _userRepo.GetByIdAsync(userId) ?? throw new Exception("用户不存在");
        user.UpdateAvatar(avatarUrl);
        await _userRepo.UpdateAsync(user);
    }

    public async Task UpdateNicknameAsync(Guid userId, string nickname)
    {
        var user = await _userRepo.GetByIdAsync(userId) ?? throw new Exception("用户不存在");
        user.UpdateNickname(nickname);
        await _userRepo.UpdateAsync(user);
    }

    public async Task ChangePasswordAsync(Guid userId, string oldPwd, string newPwd)
    {
        var user = await _userRepo.GetByIdAsync(userId) ?? throw new Exception("用户不存在");
        var oldHash = HashPassword(oldPwd, user.Salt);
        var newHash = HashPassword(newPwd, user.Salt);
        user.ChangePassword(oldHash, newHash);
        await _userRepo.UpdateAsync(user);
    }

    private string HashPassword(string pwd, string salt)
    {
        using var sha256 = System.Security.Cryptography.SHA256.Create();
        var bytes = System.Text.Encoding.UTF8.GetBytes(pwd + salt);
        var hash = sha256.ComputeHash(bytes);
        return Convert.ToBase64String(hash);
    }
}